/*
* Copyright (c) 2012 Kyle Hayward
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* 
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "Precompiled.h"

#include "D3DTextureSampler.h"
#include "Context.h"

namespace OptixDotNet 
{
	D3DTextureSampler::D3DTextureSampler( Context^ context, D3DTextureSamplerDesc desc ) : TextureSampler( context )
	{
		Create( desc );
	}	

	void D3DTextureSampler::Create( D3DTextureSamplerDesc% desc )
	{
		if( desc.Api == D3DApi::None )
			throw gcnew ArgumentException( "You must specify a Direct3D API", "desc.Api" );

		if( desc.Resource == IntPtr::Zero )
			throw gcnew ArgumentException( "You must provide a non null D3D resource", "desc.Resource" );

		pin_ptr<RTtexturesampler> ptr = &mSampler;

		if( desc.Api == D3DApi::Direct3D9 )
		{
			CheckError( rtTextureSamplerCreateFromD3D9Resource( mContext->InternalPtr(), static_cast<IDirect3DResource9*>( desc.Resource.ToPointer() ), ptr ) );
		}
		else if( desc.Api == D3DApi::Direct3D10 )
		{
			CheckError( rtTextureSamplerCreateFromD3D10Resource( mContext->InternalPtr(), static_cast<ID3D10Resource*>( desc.Resource.ToPointer() ), ptr ) );
		}
		else if( desc.Api == D3DApi::Direct3D11 )
		{
			CheckError( rtTextureSamplerCreateFromD3D11Resource( mContext->InternalPtr(), static_cast<ID3D11Resource*>( desc.Resource.ToPointer() ), ptr ) );
		}
		else
		{
			throw gcnew Exception( "D3DTextureSampler Error: Unsupported D3D API." );
		}

		SetDesc( desc );
	}

	void D3DTextureSampler::SetDesc( D3DTextureSamplerDesc% desc )
	{
		mApi = desc.Api;

		CheckError( rtTextureSamplerSetWrapMode( mSampler, 0, (RTwrapmode)desc.Wrap.WrapU ) );
		CheckError( rtTextureSamplerSetWrapMode( mSampler, 1, (RTwrapmode)desc.Wrap.WrapV ) );
		CheckError( rtTextureSamplerSetWrapMode( mSampler, 2, (RTwrapmode)desc.Wrap.WrapW ) );

		CheckError( rtTextureSamplerSetFilteringModes( mSampler, (RTfiltermode)desc.Filter.Min, (RTfiltermode)desc.Filter.Mag, (RTfiltermode)desc.Filter.Mip ) );

		CheckError( rtTextureSamplerSetReadMode( mSampler, (RTtexturereadmode)desc.Read ) );
		CheckError( rtTextureSamplerSetIndexingMode( mSampler, (RTtextureindexmode)desc.Index ) );

		CheckError( rtTextureSamplerSetMaxAnisotropy( mSampler, desc.MaxAnisotropy ) );
	}

	void D3DTextureSampler::Register()
	{
		if( mApi == D3DApi::Direct3D9 )
		{
			CheckError( rtTextureSamplerD3D9Register( mSampler ) );
		}
		else if( mApi == D3DApi::Direct3D10 )
		{
			CheckError( rtTextureSamplerD3D10Register( mSampler ) );
		}
		else if( mApi == D3DApi::Direct3D11 )
		{
			CheckError( rtTextureSamplerD3D11Register( mSampler ) );
		}
	}

	void D3DTextureSampler::Unregister()
	{
		if( mApi == D3DApi::Direct3D9 )
		{
			CheckError( rtTextureSamplerD3D9Unregister( mSampler ) );
		}
		else if( mApi == D3DApi::Direct3D10 )
		{
			CheckError( rtTextureSamplerD3D10Unregister( mSampler ) );
		}
		else if( mApi == D3DApi::Direct3D11 )
		{
			CheckError( rtTextureSamplerD3D11Unregister( mSampler ) );
		}
	}

	IntPtr D3DTextureSampler::Resource::get()
	{
		if( mApi == D3DApi::Direct3D9 )
		{
			IDirect3DResource9* resource;
			CheckError( rtTextureSamplerGetD3D9Resource( mSampler, &resource ) );
			return IntPtr( resource );
		}
		else if( mApi == D3DApi::Direct3D10 )
		{
			ID3D10Resource* resource;
			CheckError( rtTextureSamplerGetD3D10Resource( mSampler, &resource ) );
			return IntPtr( resource );
		}
		else if( mApi == D3DApi::Direct3D11 )
		{
			ID3D11Resource* resource;
			CheckError( rtTextureSamplerGetD3D11Resource( mSampler, &resource ) );
			return IntPtr( resource );
		}

		return IntPtr::Zero;
	}
}